#include "gui_app_main.h"

/****************************
 *          宏定义          *
 ****************************/
#define APP_DIAL_DIAL_SIZE      240     /* 表盘尺寸 */
#define APP_DIAL_MENU_SIZE      150     /* 表盘菜单大小 */
#define APP_DIAL_MENU_MAX_NBR   10      /* 表盘菜单项最大个数 */

#define APP_DIAL_MAIN_MENU_NAME "main"  /* 菜单主页面的名字 */

/****************************
 *       枚举和结构体        *
 ****************************/

/* 保存app的对象的链表结构 */
typedef struct APP_DIAL_MENU_LIST
{
    lv_obj_t                  *obj;
    struct APP_DIAL_MENU_LIST *next;
} app_dial_menu_list_t;

/* 使能状态 */
enum
{
    APP_DIAL_MENU_DISABLE = 0,  /* 不使能 */
    APP_DIAL_MENU_ENABLE,       /* 使能 */
};

/* 菜单(功能)结构体 */
typedef struct APP_DIAL_MENU
{
    uint8_t      status;                                            /* 状态 */
    lv_img_dsc_t *img;                                              /* 图片数据 */
    const char   *text_en;                                          /* 文本 (英文) */
    const char   *text_cn;                                          /* 文本 (中文) */
    lv_obj_t     *(*app_create)(lv_obj_t *parent, void *user_data); /* app 创建函数 */
} app_dial_menu_t;

/****************************
 *          全局变量        *
 ****************************/

/* 保存app的对象的链表头结点 */
static app_dial_menu_list_t *s_app_dial_menu_list    = NULL;
static lv_obj_t             *s_app_dial_current_menu = NULL;    /* 指向当前menu的obj指针, NULL表示停留在桌面 */
static lv_obj_t             *app_dial_root_obj       = NULL;       /* 根父节点 */
/****************************
 *          辅助函数        *
 ****************************/

/**
* @brief app追加list
* @param obj-list对象
* @retval   None
* @note 在链表结尾添加
*/
static void s_app_dial_menu_list_append(lv_obj_t *obj)
{
    if (s_app_dial_menu_list == NULL)       /* 链表为空时 */
    {
        s_app_dial_menu_list       = (app_dial_menu_list_t *) lv_mem_alloc(sizeof (app_dial_menu_list_t));
        s_app_dial_menu_list->next = NULL;
        s_app_dial_menu_list->obj  = obj;
    }
    else                            /* 链表不为空时 */
    {
        app_dial_menu_list_t *p    = s_app_dial_menu_list;
        app_dial_menu_list_t *node = (app_dial_menu_list_t *) lv_mem_alloc(sizeof (app_dial_menu_list_t));

        /* 找到为空的节点 */
        while (p)
        {
            if (p->next == NULL)
            {
                p->next    = node;
                node->next = NULL;
                node->obj  = obj;
            }

            p = p->next;
        }
    }

    return;
}

/* 创建菜单项目为空时的提示信息 */
static void s_app_dial_null_notice_mbox_event_cb(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);
    lv_obj_t * msgbox = lv_event_get_current_target(e);

    /* 校验有效性 */
    if (msgbox == NULL)
    {
        return;
    }

    if (code == LV_EVENT_PRESSED)
    {
        const char * txt = lv_msgbox_get_active_btn_text(msgbox);

        if(strcmp(txt, "apply") == 0)  /* 匹配上 'apply' */
        {
            lv_msgbox_close(msgbox);    /* 关闭 */
        }
        else if (strcmp(txt, "close") == 0) /* 匹配上 'close' */
        {
            lv_msgbox_close(msgbox);    /* 关闭 */
        }
    }

    return;
}

/**
* @brief APP空函数
* @param user_data-自定义数据
* @retval    None
*/
static lv_obj_t * s_app_dial_null_create(lv_obj_t *parent, void *user_data)
{
    (void) user_data;
    (void) parent;

    static lv_style_t msgbox_style;
    lv_style_init(&msgbox_style);          // 初始化按钮样式
    lv_style_set_radius(&msgbox_style, 22); // 设置样式圆角弧度

    static const char * btns[] ={"apply", "close", ""};

    lv_obj_t * notice_mbox = lv_msgbox_create(NULL, \
                                              "Menu Error", \
                                              "I don't want to do it right now unless you give me money.", \
                                              btns, false);

    if (notice_mbox != NULL)
    {
        lv_obj_add_style(notice_mbox, &msgbox_style, 0);
        lv_obj_align(notice_mbox, LV_ALIGN_CENTER, 0, 0);
        lv_obj_add_event_cb(notice_mbox, s_app_dial_null_notice_mbox_event_cb, LV_EVENT_PRESSED, NULL);
    }

    return NULL;
}

/**
* @brief 退出menu
* @retval    None
*/
static void s_app_dial_menu_exit_event_cb(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);
    lv_obj_t * obj = lv_event_get_target(e);

    if (code == LV_EVENT_PRESS_LOST)
    {

    }
    else if (code == LV_EVENT_PRESSED)
    {

    }
    else if (code == LV_EVENT_CLICKED)
    {
        /* 当前menu指针为NULL */
        s_app_dial_current_menu = NULL;

        /* 退出当前menu项目回到桌面 */
        lv_obj_del(lv_obj_get_parent(obj));
    }

    return;
}

/**
* @brief menu公用初始化
* @param parent-父对象
* @param title-APP标题
* @retval   创建的APP的对象
*/
static lv_obj_t * s_app_dial_menu_common_init(lv_obj_t *parent, const char *title)
{
    static lv_style_t style_btn_back;

    lv_style_init(&style_btn_back);           // 初始化按钮样式
    lv_style_set_radius(&style_btn_back, 22); // 设置样式圆角弧度

    /* 创建一个cont */
    lv_obj_t *menu_cont = lv_obj_create(parent);
    lv_obj_set_size(menu_cont, APP_DIAL_DIAL_SIZE, APP_DIAL_DIAL_SIZE);  /* 设置容器大小为表盘大小 */
    lv_obj_set_style_radius(menu_cont, LV_RADIUS_CIRCLE, 0);             /* 设置为圆形 */
    lv_obj_set_scroll_dir(menu_cont, LV_DIR_VER);                        /* 滑动方向 */
    lv_obj_set_scroll_snap_y(menu_cont, LV_SCROLL_SNAP_CENTER);
    lv_obj_set_scrollbar_mode(menu_cont, LV_SCROLLBAR_MODE_OFF);
    lv_obj_align(menu_cont, LV_ALIGN_CENTER, 0, 0);                      /* 设置对齐方式 */
    lv_obj_add_flag(menu_cont, LV_OBJ_FLAG_FLOATING);                    /* 禁止被拖动漂移 */

    /* 显示menu的title */
    lv_obj_t *label_title = lv_label_create(menu_cont);
    lv_label_set_text(label_title, title);
    lv_obj_align(label_title, LV_ALIGN_TOP_MID, 0, 0);

    /* 创建一个返回按键 */
    lv_obj_t *btn_back = lv_btn_create(menu_cont);
    lv_obj_add_style(btn_back, &style_btn_back, 0);
    lv_obj_set_size(btn_back, 50, 50);
    lv_obj_align(btn_back, LV_ALIGN_CENTER, 0, 0);
    lv_obj_add_event_cb(btn_back, s_app_dial_menu_exit_event_cb, LV_EVENT_ALL, NULL);

    /* 创建一个label */
    lv_obj_t *label_back = lv_label_create(btn_back);
    lv_label_set_text(label_back, LV_SYMBOL_LEFT);
    lv_obj_align_to(label_back, btn_back, LV_ALIGN_CENTER, 0, 0);

    /* 返回该对象 */
    return menu_cont;
}

/****************************
 *          菜单函数        *
 ****************************/

/* 首页 */
static lv_obj_t * s_app_dial_main_create(lv_obj_t *parent, void *user_data)
{
    /* menu应用初始化 */
    lv_obj_t *obj = s_app_dial_menu_common_init(parent, "main");

    /* 返回该对象 */
    return obj;
}

/* 天气功能 */
static lv_obj_t * s_app_dial_weather_create(lv_obj_t *parent, void *user_data)
{
    /* menu应用初始化 */
    lv_obj_t *obj = s_app_dial_menu_common_init(parent, "weather");
    
    /* 返回该对象 */
    return obj;
}

/* 计步功能 */
static lv_obj_t * s_app_dial_step_create(lv_obj_t *parent, void *user_data)
{
    /* menu应用初始化 */
    lv_obj_t *obj = s_app_dial_menu_common_init(parent, "step");
    
    /* 返回该对象 */
    return obj;
}

/* 心率功能 */
static lv_obj_t * s_app_dial_heart_create(lv_obj_t *parent, void *user_data)
{
    /* menu应用初始化 */
    lv_obj_t *obj = s_app_dial_menu_common_init(parent, "heart");
    
    /* 返回该对象 */
    return obj;
}

/* 血氧功能 */
static lv_obj_t * s_app_dial_oxygen_create(lv_obj_t *parent, void *user_data)
{
    /* menu应用初始化 */
    lv_obj_t *obj = s_app_dial_menu_common_init(parent, "oxygen");
    
    /* 返回该对象 */
    return obj;
}

/* 音乐功能 */
static lv_obj_t * s_app_dial_music_create(lv_obj_t *parent, void *user_data)
{
    /* menu应用初始化 */
    lv_obj_t *obj = s_app_dial_menu_common_init(parent, "music");
    
    /* 返回该对象 */
    return obj;
}

/* 相机功能 */
static lv_obj_t * s_app_dial_camera_create(lv_obj_t *parent, void *user_data)
{
    /* menu应用初始化 */
    lv_obj_t *obj = s_app_dial_menu_common_init(parent, "camera");
    
    /* 返回该对象 */
    return obj;
}

/* 罗盘功能 */
static lv_obj_t * s_app_dial_compass_create(lv_obj_t *parent, void *user_data)
{
    /* menu应用初始化 */
    lv_obj_t *obj = s_app_dial_menu_common_init(parent, "compass");
    
    /* 返回该对象 */
    return obj;
}

/* 设置功能 */
static lv_obj_t * s_app_dial_set_create(lv_obj_t *parent, void *user_data)
{
    /* menu应用初始化 */
    lv_obj_t *obj = s_app_dial_menu_common_init(parent, "set");
    
    /* 返回该对象 */
    return obj;
}

/****************************
 *        全局变量          *
 ****************************/

/* 菜单功能项的特征 */
static const app_dial_menu_t s_app_dial_menu[] = 
{ 
    /*     使能状态                      图片数据 英文名                 中文名字         创造函数*/
    {APP_DIAL_MENU_ENABLE, &icon_dial_main_clock, APP_DIAL_MAIN_MENU_NAME, NULL, s_app_dial_main_create}, /* main主页, 必须放第一个 */
    {APP_DIAL_MENU_ENABLE, &icon_dial_weather, "weather", NULL, s_app_dial_weather_create},
    {APP_DIAL_MENU_ENABLE, &icon_dial_step, "step", NULL, s_app_dial_step_create},
    {APP_DIAL_MENU_ENABLE, &icon_dial_heart, "heart", NULL, s_app_dial_heart_create},
    {APP_DIAL_MENU_ENABLE, &icon_dial_oxygen, "oxygen", NULL, s_app_dial_oxygen_create},
    {APP_DIAL_MENU_ENABLE, &icon_dial_music, "music", NULL, s_app_dial_music_create},
    {APP_DIAL_MENU_ENABLE, &icon_dial_camera, "camera", NULL, s_app_dial_camera_create},
    {APP_DIAL_MENU_ENABLE, &icon_dial_compass, "compass", NULL, s_app_dial_compass_create},
    {APP_DIAL_MENU_ENABLE, &icon_dial_set, "set", NULL, s_app_dial_set_create}
};

/****************************
 *      函数申明和实现       *
 ****************************/

/* 获取资源 */


/* 滑动菜单时触发事件(切换到下一个menu) */
static void s_app_dial_desktop_scroll_event_cb(lv_event_t * e)
{
    lv_obj_t * cont = lv_event_get_target(e);

    lv_area_t cont_a;
    lv_obj_get_coords(cont, &cont_a);
    lv_coord_t cont_y_center = cont_a.y1 + lv_area_get_width(&cont_a) / 2;

    lv_coord_t r = lv_obj_get_height(cont) * 7 / 10;
    uint32_t   i;
    uint32_t   child_cnt = lv_obj_get_child_cnt(cont);

    for (i = 0; i < child_cnt; i++) 
    {
        lv_obj_t * child = lv_obj_get_child(cont, i);
        lv_area_t child_a;
        lv_obj_get_coords(child, &child_a);

        lv_coord_t child_y_center = child_a.y1 + lv_area_get_width(&child_a) / 2;

        lv_coord_t diff_y = child_y_center - cont_y_center;
        diff_y = LV_ABS(diff_y);

        /*Get the y of diff_y on a circle.*/
        lv_coord_t y;
        lv_coord_t m;

        /*If diff_y is out of the circle use the last point of the circle (the radius)*/
        if (diff_y >= r) 
        {
            //lv_obj_set_style_size(child, 100, 0);
            y = r;
        } 
        else 
        {
            /*Use Pythagoras theorem to get x from radius and y*/
            uint32_t y_sqr = r * r - diff_y * diff_y;
            lv_sqrt_res_t res;
            lv_sqrt(y_sqr, &res, 0x8000);   /*Use lvgl's built in sqrt root function*/
            y = r - res.i;
            //lv_obj_set_style_size(child, 100-y, 0);
        }

        /*Translate the item by the calculated X coordinate*/
        lv_obj_set_style_translate_x(child, y * 2, 0);

        /*Use some opacity with larger translations*/
        lv_opa_t opa = lv_map(y, 0, r, LV_OPA_TRANSP, LV_OPA_COVER);
        lv_obj_set_style_opa(child, LV_OPA_COVER - opa, 0);
    }

    return;
}

/* 加载默认壁纸 */
static void s_app_dial_load_default_wallpaper(lv_obj_t *parent)
{
    lv_obj_t *img_desktop = lv_img_create(parent);
    lv_obj_set_size(img_desktop, APP_DIAL_DIAL_SIZE, APP_DIAL_DIAL_SIZE);  /* 设置壁纸大小为表盘大小 */
    lv_obj_set_style_radius(img_desktop, LV_RADIUS_CIRCLE, 0);             /* 设置壁纸为圆形 */
    lv_obj_align(img_desktop, LV_ALIGN_CENTER, 0, 0);                      /* 对齐方式居中 */
    lv_obj_add_flag(img_desktop, LV_OBJ_FLAG_FLOATING);                    /* 禁止被拖动漂移 */
    lv_img_set_src(img_desktop, &icon_dial_wp_sona);                       /* <------- 加载壁纸 */

    return;
}

/* 创建表盘主容器 */
static lv_obj_t * s_app_dial_create_main_cont(lv_obj_t *parent)
{
    static lv_style_t style_main_cont;  /* icon_container 样式 */

    /* 样式初始化 */
    lv_style_init(&style_main_cont);  /* style_tabview 的样式初始化 */
    lv_style_set_bg_opa(&style_main_cont, LV_OPA_0);    /* 透明 (显示壁纸) */

    /* 创建一个容器 */
    lv_obj_t * dial_cont = lv_obj_create(parent);
    lv_obj_add_style(dial_cont, &style_main_cont, 0);
    lv_obj_set_size(dial_cont, APP_DIAL_DIAL_SIZE, APP_DIAL_DIAL_SIZE);  /* 设置容器大小为表盘大小 */
    lv_obj_set_style_radius(dial_cont, LV_RADIUS_CIRCLE, 0);             /* 设置为圆形 */
    lv_obj_set_flex_flow(dial_cont, LV_FLEX_FLOW_COLUMN);                /* 子控件排列方向 */
    lv_obj_set_flex_align(dial_cont, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);  /* 子控件对齐方式 */
    lv_obj_set_style_clip_corner(dial_cont, true, 0);
    lv_obj_set_scroll_dir(dial_cont, LV_DIR_VER);                        /* 滑动方向 */
    lv_obj_set_scroll_snap_y(dial_cont, LV_SCROLL_SNAP_CENTER);
    lv_obj_set_scrollbar_mode(dial_cont, LV_SCROLLBAR_MODE_OFF);
    lv_obj_align(dial_cont, LV_ALIGN_CENTER, 0, 0);                     /* 表盘对齐方式 */
    lv_obj_add_flag(dial_cont, LV_OBJ_FLAG_FLOATING);                    /* 禁止被拖动漂移 */
    lv_obj_add_event_cb(dial_cont, s_app_dial_desktop_scroll_event_cb, LV_EVENT_SCROLL, NULL);  /* 注册事件 */

    /* 返回这个容器 */
    return dial_cont;
}

/**
* @brief ICON的事件回调函数
* @param event-事件类型
* @retval    None
* @note 根据对象找链表中的索引,根据索引执行APP
*/
static void s_app_dial_menu_click_event_cb(lv_event_t *e)
{
    uint8_t  j, k;
    uint16_t i = 0, m_c = 0, m_l = 0;
    uint8_t  page_app_nbr[GUI_APP_TAB_NBR] = {0};

    lv_event_code_t code   = lv_event_get_code(e);
    lv_obj_t       *obj    = lv_event_get_target(e);
    lv_obj_t       *parent = lv_event_get_user_data(e);

    if (code == LV_EVENT_CLICKED)
    {
        app_dial_menu_list_t * p = s_app_dial_menu_list;

        /* 在 obj链表 中匹配 obj */
        while (p)
        {
            if (p->obj == obj)
            {
                break;
            }
            i++;
            p = p->next;
        }

        /* 定位到要启动的menu, 指定父对象, 并启动 */
        s_app_dial_current_menu = s_app_dial_menu[i].app_create(parent, NULL);
    }

    return;
}

/* 创建表盘应用 */
static void s_app_dial_create_menu(lv_obj_t *parent)
{
    static lv_style_t icon_style;
    uint8_t           size = 0;    /* 菜单项尺寸大小 */
    uint8_t           i;

    /* 初始化style */
    lv_style_init(&icon_style);
    lv_style_set_text_opa(&icon_style, LV_OPA_0);

    /* 创建所有menu */
    for (i = 0; i < APP_DIAL_MENU_MAX_NBR; i++)
    {
        /* 判断该菜单功能项是否使能 (main必须使能, 所以main必能被创造) */
        if (s_app_dial_menu[i].status != APP_DIAL_MENU_ENABLE)
        {
            continue;   /* 创建下一个菜单 */
        }

        /* 判读是否有创造函数  (main必须有创造函数, 所以main必能被创造) */
        if (s_app_dial_menu[i].app_create == NULL)
        {
            continue;   /* 创建下一个菜单 */
        }

        /******************************** 区别 创建 main 或者 普通应用 ********************************/
        
        size = APP_DIAL_MENU_SIZE;  /* 普通应用的大小 */

        /* 创建 main */
        if (strcmp(s_app_dial_menu[i].text_en, APP_DIAL_MAIN_MENU_NAME) == 0)
        {
            size = APP_DIAL_DIAL_SIZE;  /* main是整个表盘的大小 */
        }

        /* 创建img */
        lv_obj_t *img_icon   = lv_img_create(parent);
        lv_obj_set_size(img_icon, size, size);   /* 设置表盘菜单大小 */
        lv_obj_set_style_radius(img_icon, LV_RADIUS_CIRCLE, 0);              /* 设置为圆形 */
        lv_img_set_src(img_icon, s_app_dial_menu[i].img);                    /* 显示图片 */

        /* main不可点击且不添加点击事件 */
        if (strcmp(s_app_dial_menu[i].text_en, APP_DIAL_MAIN_MENU_NAME) != 0)
        {
            lv_obj_add_flag(img_icon, LV_OBJ_FLAG_CLICKABLE);   /* 图标可点击 */
            lv_obj_add_event_cb(img_icon, s_app_dial_menu_click_event_cb,
                                LV_EVENT_CLICKED, app_dial_root_obj);   /* 指定事件处理函数(父对象是最基本的对象) */
        }

        /* 将该button加进menu对象链表 */
        s_app_dial_menu_list_append(img_icon);
    }

    /*Update the buttons position manually for first*/
    lv_event_send(parent, LV_EVENT_SCROLL, NULL);

    /*Be sure the fist button is in the middle*/
    lv_obj_scroll_to_view(lv_obj_get_child(parent, 0), LV_ANIM_OFF);

    return;
}

/* 创建这个项目 */
lv_obj_t * gui_app_dial_create(lv_obj_t *parent, void *user_data)
{
    /* 应用初始化 */
    lv_obj_t *obj = gui_app_common_init(parent, "app_dial", NULL);
    
    /* 创建一个app_dial的最基础的obj */
    lv_obj_t *dial_obj = lv_obj_create(obj);
    lv_obj_set_size(dial_obj, APP_DIAL_DIAL_SIZE, APP_DIAL_DIAL_SIZE);  /* 设置dial_obj大小为表盘大小 */
    lv_obj_set_style_radius(dial_obj, LV_RADIUS_CIRCLE, 0);             /* 设置dial_obj为圆形 */
    lv_obj_align(dial_obj, LV_ALIGN_CENTER, 0, 0);                      /* 对齐方式 */
    lv_obj_set_scrollbar_mode(dial_obj, LV_SCROLLBAR_MODE_OFF);         /* 隐藏滚动条 */

    /* 记录该应用最基本的对象 */
    app_dial_root_obj = dial_obj;

    /* 加载默认壁纸 */
    s_app_dial_load_default_wallpaper(app_dial_root_obj);

    /* 创建表盘主容器 */
    lv_obj_t * dial_cont = s_app_dial_create_main_cont(app_dial_root_obj);

    /* 创建表盘应用 */
    s_app_dial_create_menu(dial_cont);

    /* 返回该对象 */
    return obj;
}
